<template>
  <!-- 数值类型 -->
  <template
    v-if="
      ['number', 'quantity', 'price', 'amount', 'rate', 'percentage', 'measure'].includes(
        innerTypeRef,
      )
    "
  >
    <InputNumber
      v-bind="$attrs"
      v-model:value="innerValueRef"
      :precision="innerNumberPrecisionRef >= 0 ? innerNumberPrecisionRef : undefined"
      @change="handleChange($event)"
    >
      <template #[item]="data" v-for="item in Object.keys($slots)">
        <slot :name="item" v-bind="data || {}"></slot>
      </template>
    </InputNumber>
  </template>
  <!-- 字符类型 -->
  <template
    v-if="
      [
        undefined,
        null,
        'integer',
        'string',
        'email',
        'mobile',
        'url',
        'ipv4',
        'ipv6',
        'idcard',
        'guid',
      ].includes(innerTypeRef)
    "
  >
    <Input
      v-bind="$attrs"
      v-model:value="innerValueRef"
      @change="handleChange($event)"
      :onkeyup="
        innerTypeRef === 'integer'
          ? 'value=value.replace(/[^{1,2,3,4,5,6,7,8,9,0}]/g,\'\')'
          : 'value=value'
      "
    >
      <template #[item]="data" v-for="item in Object.keys($slots)">
        <slot :name="item" v-bind="data || {}"></slot>
      </template>
    </Input>
  </template>
  <!-- 字符扩展类型 -->
  <template v-if="['text'].includes(innerTypeRef)">
    <InputTextArea v-bind="$attrs" v-model:value="innerValueRef" @change="handleChange($event)">
      <template #[item]="data" v-for="item in Object.keys($slots)">
        <slot :name="item" v-bind="data || {}"></slot>
      </template>
    </InputTextArea>
  </template>
  <!-- 密码字符类型 -->
  <template v-if="['password'].includes(innerTypeRef)">
    <InputPassword v-bind="$attrs" v-model:value="innerValueRef" @change="handleChange($event)">
      <template #[item]="data" v-for="item in Object.keys($slots)">
        <slot :name="item" v-bind="data || {}"></slot>
      </template>
    </InputPassword>
  </template>
  <!-- 布尔字符类型 -->
  <template v-if="innerTypeRef === 'boolean'">
    <Switch v-bind="$attrs" v-model:checked="innerValueRef" @change="handleChange($event)">
      <template #[item]="data" v-for="item in Object.keys($slots)">
        <slot :name="item" v-bind="data || {}"></slot>
      </template>
    </Switch>
  </template>
  <!-- 日期时间/日期 -->
  <template v-if="['datetime', 'date'].includes(innerTypeRef)">
    <DatePicker
      v-bind="$attrs"
      :showTime="innerTypeRef === 'datetime'"
      v-model:value="innerValueRef"
      @change="handleChange($event)"
    >
      <template #[item]="data" v-for="item in Object.keys($slots)">
        <slot :name="item" v-bind="data || {}"></slot>
      </template>
    </DatePicker>
  </template>
  <!-- 时间 -->
  <template v-if="innerTypeRef === 'time'">
    <TimePicker v-bind="$attrs" v-model:value="innerValueRef" @change="handleChange($event)">
      <template #[item]="data" v-for="item in Object.keys($slots)">
        <slot :name="item" v-bind="data || {}"></slot>
      </template>
    </TimePicker>
  </template>
</template>

<script lang="ts" setup>
  import { ref, watch, unref, watchEffect } from 'vue';
  import { InputNumber, Input, Switch, DatePicker, TimePicker } from 'ant-design-vue';

  import { getPreferenceInfo } from '@/utils/preference';

  import { adInputProps } from './props';
  import type { AdInputType } from './types';

  const InputPassword = Input.Password;
  const InputTextArea = Input.TextArea;

  defineOptions({ name: 'AdInput' });
  const props = defineProps(adInputProps);
  const emit = defineEmits(['change']);

  const innerValueRef = ref();
  const innerTypeRef = ref<AdInputType>('string');
  const innerNumberPrecisionRef = ref(-1);

  function handleChange(e: any) {
    innerValueRef.value = e?.target?.value;
  }

  watchEffect(() => {
    innerValueRef.value = props.value || null;
    innerTypeRef.value = props.inputType || 'string';
    innerNumberPrecisionRef.value = -1;
    if (
      [
        'integer',
        'number',
        'quantity',
        'price',
        'amount',
        'rate',
        'percentage',
        'measure',
      ].includes(innerTypeRef.value)
    ) {
      const preferenceInfo = getPreferenceInfo();
      if (preferenceInfo !== undefined && preferenceInfo !== null) {
        switch (innerTypeRef.value) {
          case 'integer':
            innerNumberPrecisionRef.value = 0;
            break;
          case 'number':
            innerNumberPrecisionRef.value = -1;
            break;
          case 'quantity':
            innerNumberPrecisionRef.value = preferenceInfo.QuantityAccuracy || -1;
            break;
          case 'price':
            innerNumberPrecisionRef.value = preferenceInfo.PriceAccuracy || -1;
            break;
          case 'amount':
            innerNumberPrecisionRef.value = preferenceInfo.AmountAccuracy || -1;
            break;
          case 'rate':
            innerNumberPrecisionRef.value = preferenceInfo.RateAccuracy || -1;
            break;
          case 'percentage':
            innerNumberPrecisionRef.value = preferenceInfo.PercentageAccuracy || -1;
            break;
          case 'measure':
            innerNumberPrecisionRef.value = preferenceInfo.MeasureAccuracy || -1;
            break;
        }
      }
    }
  });

  watch(
    () => unref(innerValueRef),
    (val) => {
      emit('change', val);
    },
  );
</script>
